// Copyright (C) 2025 Kumo inc.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef ROTHAR_PEGTL_SRC_TEST_PEGTL_VERIFY_IMPL_HPP
#define ROTHAR_PEGTL_SRC_TEST_PEGTL_VERIFY_IMPL_HPP

#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <string>

#include <rothar/pegtl/apply_mode.hpp>
#include <rothar/pegtl/normal.hpp>
#include <rothar/pegtl/rewind_mode.hpp>

#include "result_type.hpp"
#include "test.hpp"

namespace rothar
{
   template< typename Rule, template< typename... > class Action, typename ParseInput >
   result_type verify_impl_two( ParseInput& in )
   {
#if defined( __cpp_exceptions )

      try {
         if( normal< Rule >::template match< apply_mode::action, rewind_mode::required, Action, normal >( in ) ) {
            return result_type::success;
         }
         return result_type::local_failure;
      }
      catch( const std::exception& ) {
         return result_type::global_failure;
      }
      // LCOV_EXCL_START
      catch( ... ) {
         ROTHAR_PEGTL_TEST_UNREACHABLE;
      }
      // LCOV_EXCL_STOP

#else

      if( normal< Rule >::template match< apply_mode::action, rewind_mode::required, Action, normal >( in ) ) {
         return result_type::success;
      }
      return result_type::local_failure;

#endif
   }

   template< typename Rule, template< typename... > class Action, typename ParseInput >
   void verify_impl_one( const std::size_t line, const char* file, const std::string& data, ParseInput& in, const result_type expected, const std::size_t remain )
   {
      const result_type received = verify_impl_two< Rule, Action >( in );

      if( ( received == expected ) && ( ( received == result_type::global_failure ) || ( in.size( 999999999 ) == remain ) ) ) {
         return;
      }
      ROTHAR_PEGTL_TEST_FAILED( "input data [ '" << data << "' ] result received/expected [ " << received << " / " << expected << " ] remain received/expected [ " << in.size( 999999999 ) << " / " << remain << " ]" );  // LCOV_EXCL_LINE
   }

}  // namespace rothar

#endif
